using System;
using System.Collections.Generic;
using System.Text;

namespace Toenda.Foundation.Globalization.Holiday {
	/// <summary>
	/// Implements base functiuonality for the HolidayCalendar Factory
	/// </summary>
	public abstract class HolidayCalendarFactory : IHolidayCalendarFactory {
		private List<Holiday> _holidays;
		private int _year;
		private HolidayEventType _het;

		/// <summary>
		/// Get or set the event type
		/// </summary>
		public HolidayEventType EventType {
			get { return this._het; }
			set { this._het = value; }
		}

		/// <summary>
		/// Get or set the current date
		/// </summary>
		public int CurrentYear {
			get { return this._year; }
			set { this._year = value; }
		}

		/// <summary>
		/// Get or set the holidays
		/// </summary>
		public List<Holiday> Holidays {
			get { return this._holidays; }
			set { this._holidays = value; }
		}

		/// <summary>
		/// Get the list of holidays sorted
		/// </summary>
		public List<Holiday> HolidaysSorted {
			get {
				SortedList<DateTime, Holiday> sortedList = new SortedList<DateTime, Holiday>();
				List<Holiday> list = new List<Holiday>();

				foreach(Holiday h in this.Holidays) {
					sortedList.Add(h.Date, h);
				}

				foreach(KeyValuePair<DateTime, Holiday> pair in sortedList) {
					list.Add(pair.Value);
				}

				return list;
			}
		}

		/// <summary>
		/// Get variable holidays
		/// </summary>
		public List<Holiday> VariableHolidays {
			get { return this._holidays.FindAll(delegate(Holiday f) { return !f.IsFix; }); }
		}

		/// <summary>
		/// Get fixed holidays
		/// </summary>
		public List<Holiday> FixedHolidays {
			get { return this._holidays.FindAll(delegate(Holiday f) { return f.IsFix; }); }
		}

		/// <summary>
		/// Check if a date is a holiday
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public bool IsHoliday(DateTime value) {
			return (this._holidays.Find(delegate(Holiday f) { return f.Date.Date == value.Date; }) != null);
		}

		/// <summary>
		/// Check if a date is a holiday
		/// </summary>
		/// <param name="eventType"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		public bool IsHoliday(HolidayEventType eventType, DateTime value) {
			HolidayEventType tmp = this.EventType;
			this.Initialize(eventType);
			this.EventType = tmp;

			try {
				return (this._holidays.Find(delegate(Holiday f) { return f.Date.Date == value.Date; }) != null);
			}
			catch(Exception ex) {
				throw ex;
			}
		}

		/// <summary>
		/// Get the holiday object of a date
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public Holiday GetHolidayName(DateTime value) {
			return (this._holidays.Find(delegate(Holiday f) { return f.Date.Date == value.Date; }));
		}

		/// <summary>
		/// Initialize the holidays
		/// </summary>
		/// <param name="eventType"></param>
		public abstract void Initialize(HolidayEventType eventType);
	}
}
